/*
 * Definitions for map objects.
 * Objects on the map are entities which block the tile that
 * they occupy. Actors interact with objects explicitly, i.e.
 * by pressing the interaction button. In contrast, tiles
 * with special functions can be stepped on by actors, which
 * triggers an implicit interaction. Some objects can also
 * move or be moved, as opposed to tiles, which never move.
 * The main use for having objects is as treasure chests.
 * Object behaviors are specified elsewhere since they are
 * part of the game logic, not the world definition.
 */

#ifndef MAPOBJECT_H_
#define MAPOBJECT_H_

#include "util/rect.h"
#include "util/direction.h"

typedef enum { 
	OBJ_OBSTACLE,      // solve the room puzzle to make this disappear
	OBJ_TREASURE_GOLD, // treasure chest with gold, feel free to loot
	OBJ_TREASURE_ITEM, // treasure chest with an item
	OBJ_PICKUP,        // something lying on the ground
	OBJ_LEVER,         // can be flipped, works like a TRIGGER_TOGGLE
	OBJ_SOKOBOX        // box, can be pushed around. use: sokoban puzzles
} MapObjectType;

typedef enum {
	PICKUP_GOLD,
	PICKUP_ITEM
} PickupType;

typedef struct {
	int amount;
} TreasureGoldObject;

typedef struct {
	int item;
} TreasureItemObject;

typedef struct {
	PickupType type;
	union {
		int gold_amount; // PICKUP_GOLD only
		int item;        // PICKUP_ITEM only
	};
} PickupObject;

typedef struct {
	Coord target; // lever effect depends on target tile and/or object
} LeverObject;

typedef struct {
	MapObjectType type;
	Coord coord;
	int index; // index in the map's object array
	
	// position information, supports drawing and movement
	int px_x; // draw offset from coords in pixels
	int px_y;
	int move_x; // speed of the object in pixels per tick
	int move_y;
	
	// fields with externally defined meaning
	// gfx fields are comprehended by draw routines in map_display
	// some objects may have direction- or time-dependent gfx? not sure
	// the state field value depends on the map object type
	// state field conventions: 0 = initial, 1 = finishing, 2 = finished
	// where "finish" for a map object means: to reach its end state.
	// treasure chests finish by opening; obstacles finish by disappearing.
	Direction orientation;
	int image; // may change with state and/or time
	int state;
	
	// type-specific object data
	union {
		TreasureGoldObject treasure_gold;
		TreasureItemObject treasure_item;
		PickupObject pickup;
		LeverObject lever;
	};
} MapObject;

// These constructor functions leave obj->coord unchanged.
void map_object_init (MapObject* map_object, MapObjectType type);
void map_object_make_obstacle (MapObject* map_object);
void map_object_make_treasure_gold (MapObject* map_object, TreasureGoldObject treasure);
void map_object_make_treasure_item (MapObject* map_object, TreasureItemObject treasure);
void map_object_make_lever (MapObject* map_object, Coord target);
void map_object_make_sokobox (MapObject* map_object);

#endif
